import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class LessonForm extends IEWForms {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private JButton jbtAnswer = new JButton();
	private JButton jbtSoundImage = new JButton();
	private JButton jbtNextWord = new JButton();
	private JLabel jlbAskedWord = new JLabel();
	private JLabel jlbBadWords = new JLabel();
	private JLabel jlbGoodWords = new JLabel();
	private JLabel jlbAllAnswers = new JLabel();
	private JCheckBox jcbChangeInterpritation = new JCheckBox();
	private JTextField jtfChangeInterpritation = new JTextField(200);
	
	private JTextField jtfAnswerEdit = new JTextField(200);
	
	private JPanel jpnAvailableActions = new JPanel(new BorderLayout()); // any common buttons
	private JPanel jpnAvailableSettings = new JPanel(null); // all other thing
	
	private int MAX_REITING_WORDS_COUNT_PERCENT = 20;
	private int MEDIUM_REITING_WORDS_COUNT_PERCENT = 30;
	
	private int needMaxReiting = 1;
	private int needMediumReiting = 1;
	private int needMinReiting = 1;
	private ArrayList<EW_StudiedWords> lesson = new ArrayList<EW_StudiedWords>();
	private boolean needAddWords = false;
	private int currentAnswer = 0;
	
	/**
	 * Create lesson form to do task
	 * @param parent	main form.
	 */
	public LessonForm(JFrame parent){
		super(parent, "Lesson");
		doInitForm();
		fillLessonList();
		setButtonListeners();
		if (lesson.size() == 0) {
			doCloseForm();
		}
		else {
			setQuestion();
			this.setVisible(true);
		}
	}
	
	/**
	 * insert or update studied words
	 */
	private void updateMyStudiedWords(){
		for (EW_StudiedWords word : lesson) {
			word.insertCurrentRecord();
		}
	}

	
	/*
	 * count a max number of words which required for lesson
	 */
	private void calculateRequiredNumberWords(){
		float total = myParent.profile.getAskCount()/100;
		needMaxReiting = Math.round(total*MAX_REITING_WORDS_COUNT_PERCENT);
		needMediumReiting = Math.round(total*MEDIUM_REITING_WORDS_COUNT_PERCENT);
		if (needMaxReiting == 0)
			needMaxReiting = 1;
		if (needMediumReiting == 0)
			needMediumReiting = 1;
		needMinReiting = myParent.profile.getAskCount() - (needMediumReiting + needMaxReiting); 
	}
	
	/**
	 * create asking list group.
	 */
	private void fillLessonList(){
		calculateRequiredNumberWords(); // counting the required number of words desired group
		int MAX_DAYS = 7 * 8640000; // count days number in milliseconds for max quality
		int MED_DAYS = 3 * 8640000; // count days number in milliseconds for medium quality
		EW_StudiedWords inst = new EW_StudiedWords(needMaxReiting, myParent.profile.getName()); // prepared class for selections
		HashMap<String, String> keys = new HashMap<String, String>(); // preparing query set
		keys.put("tensCount", " > 2");
		keys.put("lastAsk", new Timestamp(new Date().getTime() - MAX_DAYS).toString());
		keys.put("name", myParent.profile.getName());
		String topic = myParent.jcbTopic.getSelectedItem().toString();
		if (myParent.jcbTopic.getSelectedIndex() != 0)
			keys.put("topicName", topic);
		// fill temporary list for max quality words
		ArrayList<EW_StudiedWords> temp = inst.getList(keys);
		if (temp.size() < needMaxReiting){
			needMediumReiting += needMaxReiting - temp.size(); // increase required medium words count   
		}
		lesson.addAll(temp);
		// change query set for medium quality
		inst.setNeedsCount(needMediumReiting);
		keys.put("tensCount", " BETWEEN 1 AND 2");
		keys.put("lastAsk", new Timestamp(new Date().getTime() - MED_DAYS).toString());
		// fill list
		temp = inst.getList(keys);
		if (temp.size() < needMediumReiting){
			needMinReiting += needMediumReiting - temp.size();  // increase required minimum words count
		}
		lesson.addAll(temp);
		// change query set for minimum quality
		inst.setNeedsCount(needMinReiting);
		keys.put("tensCount", " < 1");
		keys.put("lastAsk", new Timestamp(new Date().getTime() - (myParent.profile.getRestTime() * 100)).toString());
		temp = inst.getList(keys);
		lesson.addAll(temp);
		// if necessary try to get new fords from list
		if (lesson.size() < myParent.profile.getAskCount()){
			EW_Vocabulary word = new EW_Vocabulary(new EW_Alphabet(myParent.profile.getStudyLanguage(), ""));
			int count = myParent.profile.getAskCount() - lesson.size();
			ArrayList<EW_Vocabulary> list = null;
			if (myParent.jcbTopic.getSelectedIndex() == 0) {
				list = word.getListOfNewWords(count, myParent.profile.getName(), "");
			}
			else {
				list = word.getListOfNewWords(count, myParent.profile.getName(), topic);
			}
			
			for (EW_Vocabulary item : list ) {
				EW_StudiedWords studied = new EW_StudiedWords(1, myParent.profile.getName());
				studied.setCurrentWord(item);
				studied.setPoints(0.00);
				lesson.add(studied);
			}
		}
		// if it's still need, after finish asking new words
		if (lesson.size() < myParent.profile.getAskCount()){
			needAddWords = true; 
		}
	}
	
	@Override
	public void doInitForm() {
		setLabelsName();
		int fWidth = this.getWidth();
		this.setLayout(new BorderLayout());
		this.add(jpnAvailableActions, BorderLayout.SOUTH);
		this.add(jpnAvailableSettings, BorderLayout.CENTER);
		
		jlbAskedWord.setBounds(5, 5, fWidth - 10, 25);
		jlbAskedWord.setFont(new Font("Arial", Font.BOLD, 25));
		
		jbtSoundImage.setBounds(5, 35, 50, 50);
		jcbChangeInterpritation.setBounds(5, 90, fWidth - 10, 25);
		jlbBadWords.setBounds(5, 110, fWidth - 10, 25);
		jlbGoodWords.setBounds(5, 130, fWidth - 10, 25);
		jlbAllAnswers.setBounds(5, 150, fWidth - 10, 25);
		jtfChangeInterpritation.setBounds(5, 180,fWidth - 10, 25);
		
		jpnAvailableActions.setPreferredSize(new Dimension(fWidth, 55));
		jpnAvailableActions.add(jtfAnswerEdit, BorderLayout.CENTER);
			
		JPanel jpnActions = new JPanel(new BorderLayout());
		jpnActions.add(jbtAnswer, BorderLayout.WEST);
		jpnActions.add(jbtNextWord, BorderLayout.EAST);
		jpnAvailableActions.add(jpnActions, BorderLayout.SOUTH);
		
		jpnAvailableSettings.add(jbtSoundImage);
		jpnAvailableSettings.add(jlbAskedWord);
		
		jpnAvailableSettings.add(jlbBadWords);
		jpnAvailableSettings.add(jlbGoodWords);
		jpnAvailableSettings.add(jlbAllAnswers);
		jpnAvailableSettings.add(jcbChangeInterpritation);
		jpnAvailableSettings.add(jtfChangeInterpritation);
		
	}

	@Override
	public void setButtonListeners() {
		jbtAnswer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String[] allAnswersWords = jtfAnswerEdit.getText().split("[,;]"); // fill array of answers
				EW_Vocabulary word = lesson.get(currentAnswer).getCurrentWord(); // get word from list
				String[] allCheckedWords = word.getInterpretation().split("[,;]"); // fill array of answers key
				
				int goodWords = 0; 
				int badWords = 0;
				ArrayList<String> badWordsToShow = new ArrayList<String>(); // create new list of bad words
				ArrayList<String> goodWordsToShow = new ArrayList<String>(); // create new list of good words
				String semple = "";
				String wordKey = "";
				for (int i = 0; i < allAnswersWords.length; i++) { // do check for correct answers
					semple = allAnswersWords[i].trim().toLowerCase();
					for (int j = 0; j < allCheckedWords.length; j++) {
						wordKey = allCheckedWords[j].trim().toLowerCase();
						if (semple.equals(wordKey)){
							if (goodWordsToShow.indexOf(semple) == -1){
								goodWords++;
								goodWordsToShow.add(semple);
							}
							break;
						}
						if (j == allCheckedWords.length - 1) {
							if (badWordsToShow.indexOf(semple) == -1){
								badWordsToShow.add(semple);
								badWords++;
							}
						}
					}
				}
				// calculate new rating
				double pointsResult = 0.00;
				if (goodWords > 0) {
					pointsResult = 1 + (1 - ((double)goodWords/allCheckedWords.length));
					if (badWords > 0){
						pointsResult -= ((double)badWords * 2/allAnswersWords.length); 
					}
				}
				else {
					pointsResult = -5.00;
				}
				
				if (pointsResult < -5.00)
					pointsResult = -5.00;
				
				// set new rating for studied word
				lesson.get(currentAnswer).setPoints(pointsResult);
				setAnswerToLabel(goodWordsToShow, badWordsToShow);
			}
		});
		
		jbtSoundImage.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		
		jbtNextWord.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				currentAnswer++;
				if (currentAnswer == lesson.size()) {
					updateMyStudiedWords();
					doCloseForm();
				} 
				else {
					if (jcbChangeInterpritation.isSelected()){
						EW_Vocabulary curWord = lesson.get(currentAnswer - 1).getCurrentWord();
						curWord.setInterpretation(jtfChangeInterpritation.getText());
						curWord.updateCurrentRecord();
						jtfChangeInterpritation.setText("");
						jtfChangeInterpritation.setVisible(false);
						jcbChangeInterpritation.setSelected(false);
					}
					setQuestion();
					jtfAnswerEdit.requestFocusInWindow();
				}
			}
		});
		
		jcbChangeInterpritation.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if (jcbChangeInterpritation.isSelected()){
					jtfChangeInterpritation.setText(lesson.get(currentAnswer).getCurrentWord().getInterpretation());
					jtfChangeInterpritation.setVisible(true);
				}
				else {
					jtfChangeInterpritation.setVisible(false);
				}
				
			}
		});
		
	}
	
	private void doCloseForm(){
		myParent.changeTimerStatus();
		jbtAnswer.removeActionListener(jbtAnswer.getActionListeners()[0]);
		jbtNextWord.removeActionListener(jbtNextWord.getActionListeners()[0]);
		jbtSoundImage.removeActionListener(jbtSoundImage.getActionListeners()[0]);
		this.dispose();
		if (needAddWords){
			myParent.callNewLessonForm();
		}		
	}
	
	/**
	 * Show answer result, bad and good answer
	 * @param goodAnswer	array of good answers
	 * @param badAnswer		array of bad answers
	 */
	private void setAnswerToLabel(ArrayList<String> goodAnswer, ArrayList<String> badAnswer){
		jlbAllAnswers.setText(lesson.get(currentAnswer).getCurrentWord().getInterpretation());
		String good = "";
		for (String str : goodAnswer) {
			good += str + ", ";
		}
		String bad = "";
		for (String str : badAnswer) {
			bad += str + ", ";
		}
		jlbBadWords.setText(bad);
		jlbGoodWords.setText(good);
		
		jbtNextWord.setEnabled(true);
		jbtAnswer.setEnabled(false);
		jcbChangeInterpritation.setEnabled(true);
	}
	
	/**
	 * prepare form for asking.
	 */
	private void setQuestion(){
		String word = lesson.get(currentAnswer).getCurrentWord().getWord();
		jlbAskedWord.setText(word);
		jtfAnswerEdit.setText("");
		
		jlbAllAnswers.setText("");
		jlbBadWords.setText("");
		jlbGoodWords.setText("");
		jbtNextWord.setEnabled(false);
		jbtAnswer.setEnabled(true);
		jcbChangeInterpritation.setEnabled(false);
	}

	@Override
	public void setLabelsName() {
		jbtAnswer.setText("Ответить");
		jbtNextWord.setText("Следующее");
		jcbChangeInterpritation.setText("Изменить перевод слова");
		jcbChangeInterpritation.setEnabled(false);
		jtfChangeInterpritation.setVisible(false);
		jbtSoundImage.setIcon(new ImageIcon(this.getClass().getResource("resurse/sound.gif")));
		jlbBadWords.setForeground(Color.RED);
		jlbGoodWords.setForeground(Color.GREEN);

	}
	
}
